﻿#define  _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<functional>



//#include<memory>

//class Exception
//{
//public :
//	Exception(const std::string& errmsg, int id)
//		: _errmsg(errmsg)
//		, _id(id)
//	{}
//	virtual std::string what() const
//	{
//		return _errmsg;
//	} 
//	int getid() const
//	{
//		return _id;
//	}
//protected:
//	std::string _errmsg;
//	int _id;
//};
//
//
//double Divide(int a, int b)
//{
//	// 当b == 0时抛出异常
//	if (b == 0)
//	{
//		throw "Divide by zero condition!";
//	} 
//	else
//	{
//	return (double)a / (double)b;
//	}
//}
//
//
//template<class T>
//class SmartPtr
//{
//public:
//	//RAII
//	SmartPtr(T* ptr)
//		:_ptr(ptr)
//	{}
//
//	~SmartPtr()
//	{
//		std::cout << "delete[] " << _ptr << std::endl;
//		delete[] _ptr;
//	}
//
//	//重载运算符。模拟指针行为，方便访问资源
//	T& operator* ()
//	{
//		return *_ptr;
//	}
//
//	T& operator[](size_t i)
//	{
//		return _ptr[i];
//	}
//
//	T* operator-> ()
//	{
//		return _ptr;
//	}
//
//
//
//private:
//	T* _ptr;
//};
//
//void Func()
//{
//	SmartPtr<int> sp1 = new int[10];
//	SmartPtr<int> sp2 = new int[10];
//	for (size_t i = 0; i < 10; i++)
//	{
//		sp1[i] = sp2[i] = i;
//	} 
//	int len, time;
//	std::cin >> len >> time;
//	std::cout << Divide(len, time) << std::endl;
//}
//
//
//
//int main()
//{
//	try
//	{
//		Func();
//	}
//	catch(const char* errmsg)
//	{
//		std::cout << errmsg << std::endl;
//	} 
//	catch(const Exception & e)
//	{
//		std::cout << e.what() << std::endl;
//	} 
//	catch(...)
//	{
//		std::cout << "未知异常" << std::endl;
//	}
//	return 0;
//}


struct Date
{
	int _year;
	int _month;
	int _day;
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{}

	~Date()
	{
		std::cout << "~Date()" << std::endl;
	}
};


namespace Cw
{
	

	template<class T>
	class auto_ptr
	{
	public:
		auto_ptr(T* ptr)
			:_ptr(ptr)
		{}

		auto_ptr(const auto_ptr<T>& sp)
			:_ptr(sp._ptr)
		{
			//管理权转移，被拷贝对象指针悬空
			sp._ptr = nullptr;
		}

		auto_ptr<T>& operator = (auto_ptr<T>& ap)
		{
			if (this != &ap)
			{
				if (_ptr)
				{
					//释放当前对象中的资源
					if (_ptr)
						delete _ptr;

					//转移ap中资源到当前对象中
					_ptr = ap._ptr;
					ap._ptr = nullptr;
				}
			}
		   return *this;
		}

		~auto_ptr()
		{
			if (_ptr)
			{
				std::cout << "delete:" << _ptr << std::endl;
				delete _ptr;
			}
		}

		// 像指针⼀样使⽤
		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}

	private:
		T* _ptr;
	};

	template<class T>
	class unique_ptr
	{
	public:
		explicit unique_ptr(T* ptr)
			:_ptr(ptr)
		{}

		~unique_ptr()
		{
			if (_ptr)
			{
				std::cout << "delete:" << _ptr << std::endl;
				delete _ptr;
			}
		}
		unique_ptr(const unique_ptr<T>& uq) = delete;
		unique_ptr<T>& operator=(const unique_ptr<T>& uq) = delete;
		unique_ptr(unique_ptr<T>&& uq)
			:_ptr(uq._ptr)
		{
			uq._ptr = nullptr;
		}

		unique_ptr<T>& operator = (unique_ptr<T> && up)
		{
			delete _ptr;
			_ptr = up._ptr;
			up._ptr = nullptr;
		}

			// 像指针⼀样使⽤
			T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}

	private:
		T* _ptr;
	};


	template<class T>
	class shared_ptr
	{
	public:
		explicit shared_ptr(T* ptr = nullptr)
			:_ptr(ptr)
			, _pcount(new int(1))
		{}

		template<class D>
		shared_ptr(T* ptr, D del)
			: _ptr(ptr)
			, _pcount(new int(1))
			, _del(del)
		{}

		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr)
			, _pcount(sp._pcount)
			, _del(sp._del)
		{
			(*_pcount)++;
		}

		void release()
		{
			if (--(*_pcount) == 0)
			{
				// 最后一个管理的对象，释放资源
				_del(_ptr);
				delete _pcount;
				_ptr = nullptr;
				_pcount = nullptr;
			}
		}

		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
		{

			if (_ptr != sp._ptr)
			{
				release();
				_ptr = sp._ptr;
				_pcount = sp._pcount;
				++(*_pcount);
				_del = sp._del;
			}
			return *this;
		}

		~shared_ptr()
		{
			release();
		}

		T* get() const
		{
			return _ptr;
		}

		int use_count() const
		{
			return *_pcount;
		}

		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}

	private:
		T* _ptr;
		int* _pcount; //引用计数
		std::function<void(T*)> _del = [](T* ptr) {delete ptr; }; //删除器
	};
}

class Fclose
{
public:
	void operator()(FILE* ptr)
	{
		std::cout << "fclose:" << ptr << std::endl;
		fclose(ptr);
	}
};



void test_smartptr()
{
	Cw::shared_ptr<Date> sp1(new Date);
	Cw::shared_ptr<Date> sp2(sp1);
	Cw::shared_ptr<Date> sp3(sp2);
	std::cout << sp1.use_count() << std::endl;
	sp1->_year++;
	std::cout << sp1->_year << std::endl;
	std::cout << sp2->_year << std::endl;
	std::cout << sp3->_year << std::endl;

	Cw::shared_ptr<Date> sp4(new Date[10], [](Date* ptr) {delete[] ptr; });
	Cw::shared_ptr<FILE> sp5(fopen("test.cpp", "r"), Fclose());
}



int main()
{
	test_smartptr();
	return 0;
}


















